package br.com.infoanalise.arq.negocio.repository.impl;

import java.util.List;

import javax.inject.Inject;
import javax.persistence.EntityManagerFactory;

import org.springframework.orm.jpa.support.JpaDaoSupport;

import br.com.infoanalise.arq.negocio.exceptions.DataAccessException;
import br.com.infoanalise.arq.negocio.repository.Persistable;
import br.com.infoanalise.arq.negocio.repository.Repository;

/**
 * Classe base de implementacao do repositorio, utilizando o hibernate como
 * framework para Mapeamento Objeto Relacional
 * 
 * @author Fabiano Fernandes de Oliveira
 */
public abstract class AbstractJpaRepository<T extends Persistable> extends
		JpaDaoSupport implements Repository<T> {



	@Override
	public T getById(Long id) throws DataAccessException {
		return (T) getJpaTemplate().find(getEntityClass(), id);
	}

	@Override
	public List<T> getAll() throws DataAccessException {
		return getJpaTemplate().find("from " + getEntityClass().getName());
	}

	@Override
	public Long getCountAll() throws DataAccessException {
		return (Long) getJpaTemplate()
				.getEntityManagerFactory()
				.createEntityManager()
				.createQuery(
						"select count(*) from " + getEntityClass().getName())
				.getSingleResult();
	}

	@Override
	public void persist(T obj) throws DataAccessException {
		getJpaTemplate().persist(obj);
	}

	@Override
	public void merge(T obj) throws DataAccessException {
		getJpaTemplate().merge(obj);
	}

	@Override
	public void save(T obj) throws DataAccessException {
		if (getJpaTemplate().contains(obj)) {
			getJpaTemplate().merge(obj);
		} else {
			getJpaTemplate().persist(obj);
		}
		getJpaTemplate().flush();
	}

	@Override
	public void remove(T obj) throws DataAccessException {
		getJpaTemplate().remove(obj);
	}

	@Override
	public List<T> getByAttribute(String attribute, Object value)
			throws DataAccessException {
		StringBuffer query = new StringBuffer("from ");
		query.append(getEntityClass().getName());
		query.append(" where ");
		// se for uma String, adiciona o upper
		if (value instanceof String) {
			query.append("upper(");
			query.append(attribute);
			query.append(") = upper(?)");

		} else {
			query.append(attribute);
			query.append(" = ? ");

		}
		return getJpaTemplate().find(query.toString(), value);
	}

	@Override
	public List<T> getLikeByAttribute(String attribute, String value)
			throws DataAccessException {
		value = "%" + value + "%";
		return getJpaTemplate().find(
				"from " + getEntityClass().getName() + " where upper("
						+ attribute + ") like upper(?) ", value);
	}

}
